#include "napi/native_api.h"
#include "multimodalinput/oh_input_manager.h"
#include <cstdint>
#include <cstdlib>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sstream>
// 全局变量
std::string g_value = "";
int32_t g_eventId = -1;
std::string g_history = "";

// JS 回调函数
napi_ref g_callback_ref = nullptr;
napi_env g_env = nullptr;

//当 g_value 变化时，通知 JS
void NotifyValueChange() {
    if (g_callback_ref == nullptr || g_env == nullptr) {
        return;
    }

    napi_value callback;
    napi_get_reference_value(g_env, g_callback_ref, &callback);
    
    //callback的输入参数
    napi_value event;
    napi_create_object(g_env, &event);
    
    napi_value value_js;
    napi_create_string_utf8(g_env, g_value.c_str(), g_value.length(), &value_js);
    napi_set_named_property(g_env, event, "value", value_js);
    napi_value eventId_js;
    napi_create_int32(g_env, g_eventId, &eventId_js);
    napi_set_named_property(g_env, event, "eventId", eventId_js);
    napi_value history_js;
    napi_create_string_utf8(g_env, g_history.c_str(), g_history.length(), &history_js);
    napi_set_named_property(g_env, event, "history", history_js);


    napi_value global;
    napi_get_global(g_env, &global);
    napi_call_function(g_env, global, callback, 1, &event, nullptr);
}

//注册回调
napi_value OnChange(napi_env env, napi_callback_info info) {
    g_env = env;
    size_t argc = 1;
    napi_value args[1];
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    // 保存 callback 引用
    napi_create_reference(env, args[0], 1, &g_callback_ref);
    return nullptr;
}


//设置字符串值
napi_value SetGValue(napi_env env, napi_callback_info info) {
    size_t argc = 1;
    napi_value args[1];
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    // 获取 JS 传入的字符串
    char buffer[256];
    size_t copied;
    napi_get_value_string_utf8(env, args[0], buffer, sizeof(buffer), &copied);
    g_value = std::string(buffer, copied);
    // 变化后立即通知 JS
    NotifyValueChange();
    return nullptr;
}

char KeyCodeToChar(int32_t keyCode) {
    if (keyCode >= 2017 && keyCode <= 2042) {
        return static_cast<char>('A' + (keyCode - 2017));
    }
    return '\0';
}

void TestKeyEventCallback(const Input_KeyEvent* keyEvent){
    int eventId = -1;
    Input_Result res = OH_Input_GetKeyEventId(keyEvent, &eventId);
    int32_t action = OH_Input_GetKeyEventAction(keyEvent);
    int32_t keyCode = OH_Input_GetKeyEventKeyCode(keyEvent);
    int64_t time = OH_Input_GetKeyEventActionTime(keyEvent);
    int32_t windowId = OH_Input_GetKeyEventWindowId(keyEvent);
    int32_t displayId = OH_Input_GetKeyEventDisplayId(keyEvent);
    if (action == 2) {
        return;
    }
    std::ostringstream oss;
    oss << "拦截callback: "
    << "KeyEvent - Id: " << eventId
    << ", KeyEvent - Action: " << action
    << ", KeyCode: " << keyCode
    << ", Time: " << time
    << ", WindowId: " << windowId
    << ", DisplayId: " << displayId;
    if (keyCode > 2009 || keyCode < 2000) {
        Input_Result res = OH_Input_DispatchToNextHandler(eventId);
        if (res != INPUT_SUCCESS) {
            oss << "\n输入非数字，执行DispatchToNextHandlers失败，code:" + std::to_string(res);
        } else {
            oss << "\n输入非数字，执行DispatchToNextHandlers成功";
        }
    } else {
        oss << "\n输入为数字"+ std::to_string(keyCode - 2000) +"，不执行DispatchToNextHandlers";
        g_history += std::to_string(keyCode - 2000);
    }
    g_value = oss.str();
    g_eventId = eventId;
    NotifyValueChange();
}

static napi_value AddKeyEventHook(napi_env env, napi_callback_info info)
{
    g_value = "进入添加拦截函数";
    NotifyValueChange();
    Input_Result res = OH_Input_AddKeyEventHook(TestKeyEventCallback);
    NotifyValueChange();
    if (res != INPUT_SUCCESS) {
        g_value =  "添加拦截失败,code: " + std::to_string(res);
        NotifyValueChange();
    } else {
            std::ostringstream oss;
        oss << "添加拦截完成, 回调函数地址: " << std::hex << reinterpret_cast<uintptr_t>(TestKeyEventCallback);
        g_value =  oss.str();
        NotifyValueChange();
    }
    return nullptr;
}

static napi_value RemoveKeyEventHook(napi_env env, napi_callback_info info)
{
    g_value = "进入移除拦截函数";
    g_history = "";
    NotifyValueChange();
    Input_Result res = OH_Input_RemoveKeyEventHook(TestKeyEventCallback);
    if (res != INPUT_SUCCESS) {
        g_value =  "移除拦截失败,code: " + std::to_string(res);
        NotifyValueChange();
    } else {
        std::ostringstream oss;
        oss << "移除拦截完成, 回调函数地址: " << std::hex << reinterpret_cast<uintptr_t>(TestKeyEventCallback);
        g_value =  oss.str();
        NotifyValueChange();
    }
    return nullptr;
}


static napi_value DispatchToNextHandler(napi_env env, napi_callback_info info)
{
    Input_Result res = OH_Input_DispatchToNextHandler(g_eventId);
    if (res == INPUT_SUCCESS){
        g_value =  "DispatchToNextHandler成功,eventId为" + std::to_string(g_eventId);
        NotifyValueChange();
    } else {
        g_value =  "DispatchToNextHandler失败,eventId为" + std::to_string(g_eventId);
        NotifyValueChange();
    }
    return nullptr;
}

EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports)
{
    napi_property_descriptor desc[] = {

        { "onChange", nullptr, OnChange, nullptr, nullptr, nullptr, napi_default, nullptr },
        { "setGValue", nullptr, SetGValue, nullptr, nullptr, nullptr, napi_default, nullptr },
        { "RemoveKeyEventHook", nullptr, RemoveKeyEventHook, nullptr, nullptr, nullptr, napi_default, nullptr },
        { "AddKeyEventHook",    nullptr, AddKeyEventHook,    nullptr, nullptr, nullptr, napi_default, nullptr },
        { "DispatchToNextHandler", nullptr, DispatchToNextHandler, nullptr, nullptr, nullptr, napi_default, nullptr },
    };
    napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
    return exports;
}
EXTERN_C_END

static napi_module demoModule = {
    .nm_version = 1,
    .nm_flags = 0,
    .nm_filename = nullptr,
    .nm_register_func = Init,
    .nm_modname = "entry",
    .nm_priv = ((void*)0),
    .reserved = { 0 },
};

extern "C" __attribute__((constructor)) void RegisterEntryModule(void)
{
    napi_module_register(&demoModule);
}
